package com.hy.convenient.controller.login;

import com.alibaba.fastjson.JSONObject;
import com.hy.convenient.pojo.login.UsersPojo;
import com.hy.convenient.service.login.UsersService;
import com.hy.convenient.tool.CommonSeesionTool;
import com.hy.convenient.tool.RedisUitl;
import com.hy.convenient.tool.VerifyCode;
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Controller
public class LoginController {
    @Autowired
    private RedisUitl redisUitl;
    @Autowired
    private UsersService usersService;
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    @ResponseBody
    public String defaultLogin() {
        return "";
    }
    @RequestMapping(value = "/loginOut", method = RequestMethod.POST)
    @ResponseBody
    public  Map<String, Object> loginOut(){
        Subject subject = SecurityUtils.getSubject();
        redisUitl.remove( subject.getSession().getId().toString());
        subject.logout();
        Map<String, Object> result = new HashMap<>();
        result.put("code", 200);
        return  result;
    }
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> login(@RequestParam("username") String userId, @RequestParam("password") String password) {
        // 从SecurityUtils里边创建一个 subject
        Subject subject = SecurityUtils.getSubject();
        // 在认证提交前准备 token（令牌）
        UsernamePasswordToken token = new UsernamePasswordToken(userId, password);
        Map<String, Object> result = new HashMap<>();
        result.put("code", 200);
        result.put("msg", "");
        // 执行认证登陆
        try {
            subject.login(token);
        } catch (UnknownAccountException uae) {
            result.put("msg", "未知账户");
        } catch (IncorrectCredentialsException ice) {
            result.put("msg", "密码不正确");
        } catch (LockedAccountException lae) {
            result.put("msg", "账户已锁定");
        } catch (ExcessiveAttemptsException eae) {
            result.put("msg", "用户名或密码错误次数过多");
        } catch (AuthenticationException ae) {
            result.put("msg", "用户名或密码不正确");
        }
        if (subject.isAuthenticated()) {
            Map<String, Object> map = new HashMap<>();
            map.put("userId",userId);
            map.put("userPass",password);
            UsersPojo usersPojo = usersService.queryByLogin(map);
            String json=JSONObject.toJSONString(usersPojo);
            redisUitl.set(subject.getSession().getId().toString(),json);
            result.put("session", subject.getSession().getId());
            result.put("msg", "登录成功");
        } else {
            token.clear();
            result.put("code", 100);
            result.put("msg", "登录失败");
        }
        return  result;
    }

    @RequestMapping(value = "/userInfo")
    @ResponseBody
    public UsersPojo userInfo(HttpServletRequest request) {
        Object seesionId = CommonSeesionTool.getSeesionId(request);
        return   redisUitl.getObject(seesionId.toString());
    }

    /**
     * 获取登录时的验证码
     * @return
     */
    /* 获取验证码图片*/
    @RequestMapping("/getVerifyCode")
    public void getVerificationCode(HttpServletResponse response, HttpServletRequest request) {
        try {
            int width=200;
            int height=69;
            BufferedImage verifyImg=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//生成对应宽高的初始图片
            String randomText = VerifyCode.drawRandomText(width,height,verifyImg);
//单独的一个类方法，出于代码复用考虑，进行了封装。
//功能是生成验证码字符并加上噪点，干扰线，返回值为验证码字符
            request.getSession().setAttribute("verifyCode", randomText);
            response.setContentType("image/png");//必须设置响应内容类型为图片，否则前台不识别
            OutputStream os = response.getOutputStream(); //获取文件输出流
            ImageIO.write(verifyImg,"png",os);//输出图片流
            os.flush();
            os.close();//关闭流
            //写入缓存
            redisUitl.set(request.getRemoteAddr(),randomText,5, TimeUnit.MINUTES);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
